/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package htmlparser;

import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
import DataBase.Ficheiro;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.net.URLDecoder;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.text.BadLocationException;

public class UrlParser {

    public UrlParser() {
    }
    private String type;

    /**
     * get's the values for HREF and SRC
     *
     * @param filePath path of the html file to perse
     * @param type type of tag ti look (img, image, a, link, all)
     *
     * @return
     */
    public ArrayList<Ficheiro> getUrl(Ficheiro dbObj, String type) {
        String filePath = dbObj.getCaminholocal();
        final ArrayList<String> attributeList = new ArrayList<>();
        final ArrayList<String> ImgList = new ArrayList<>();
        final ArrayList<String> returnValue;
        final URLDecoder t = new URLDecoder();
        ParserDelegator parserDelegator = new ParserDelegator();

        HTMLEditorKit.ParserCallback parserCallback = new HTMLEditorKit.ParserCallback() {
            public void handleText(final char[] data, final int pos) {
            }

            public void handleStartTag(HTML.Tag tag, MutableAttributeSet attribute, int pos) {
                if (tag == HTML.Tag.A) {
                    String domain = socof_webcrawler.SOCOF_WebCrawler.getDOMAIN();
                    String address = (String) attribute.getAttribute(HTML.Attribute.HREF);
                    address = t.decode(address);
                    try {
                        if (address.toLowerCase().contains(domain) && !address.equals(null)) {
                            attributeList.add(address);
                        } else {
                            String lastCaract = domain.substring(domain.length() - 1);
                            if (lastCaract.compareTo("/") == 1) {
                                domain = domain.substring(0, domain.length() - 1);
                            }
                            attributeList.add(domain + address);
                        }
                    } catch (Exception e) {
                        System.err.println("Exception: " + e.getMessage());
                    }
                }
                //Aqui captura as imagens
                if (tag == HTML.Tag.IMG) {
                    String domain = socof_webcrawler.SOCOF_WebCrawler.getDOMAIN();
                    String address = (String) attribute.getAttribute(HTML.Attribute.SRC);
                    address = t.decode(address);
                    try {
                        if (address.toLowerCase().contains(domain) && !address.equals(null)) {
                            ImgList.add(address);
                        } else {
                            String lastCaract = domain.substring(domain.length() - 1);
                            if (lastCaract.compareTo("/") == 0) {
                                domain = domain.substring(0, domain.length() - 1);
                            }
                            ImgList.add(domain + address);
                        }
                    } catch (Exception e) {
                        System.err.println("Exception: " + e.getMessage());
                    }
                }

            }

            public void handleEndTag(HTML.Tag tag, final int pos) {
            }

            public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attribute, final int pos) {
//                if (tag == HTML.Tag.A) {
//                    String domain = socof_webcrawler.SOCOF_WebCrawler.getDOMAIN();
//                    String address = (String) attribute.getAttribute(HTML.Attribute.HREF);
//                    address = t.decode(address);
//                    try {
//                        if (address.toLowerCase().contains(domain) && !address.equals(null)) {
//                            attributeList.add(address);
//                        } else {
//                            String lastCaract = domain.substring(domain.length() - 1);
//                            if (lastCaract.compareTo("/") == 0) {
//                                domain = domain.substring(0, domain.length() - 1);
//                            }
//                            attributeList.add(domain + address);
//                        }
//                    } catch (Exception e) {
//                        System.err.println("Exception: " + e.getMessage());
//                    }
//                }
//                //Aqui captura as imagens
//                if (tag == HTML.Tag.IMG) {
//                    String domain = socof_webcrawler.SOCOF_WebCrawler.getDOMAIN();
//                    String address = (String) attribute.getAttribute(HTML.Attribute.SRC);
//                    address = t.decode(address);
//
//                    try {
//                        if (address.toLowerCase().contains(domain) && !address.equals(null)) {
//                            ImgList.add(address);
//                        } else {
//                            String lastCaract = domain.substring(domain.length() - 1);
//                            if (lastCaract.compareTo("/") == 0) {
//                                domain = domain.substring(0, domain.length() - 1);
//                            }
//                            ImgList.add(domain + address);
//                        }
//                    } catch (Exception e) {
//                        System.err.println("Exception: " + e.getMessage());
//                    }
//                }
            }

            public void handleComment(final char[] data, final int pos) {
            }

            public void handleError(final java.lang.String errMsg, final int pos) {
                try {
                    // work around bug in the parser that fails to call flush
                    flush();
                } catch (BadLocationException ex) {
                    Logger.getLogger(UrlParser.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        };
        try {
//            this.removeHeaderMetaTag(filePath);
            FileReader file = new FileReader(filePath);
            parserDelegator.parse(file, parserCallback, true);
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }

        //Aqui é onde se decide o que devolve
        type = type.toLowerCase();
        switch (type) {
            case "img":
            case "image":
                returnValue = ImgList;
                break;
            case "a":
            case "link":
                returnValue = attributeList;
                break;
            case "all":
            default:

                for (String img : ImgList) {
                    attributeList.add(img);
                }
                returnValue = attributeList;
                break;
        }

        ArrayList<Ficheiro> attributes = this.turn2File(returnValue, dbObj, type);
        boolean parsedResult;
        LinkChanger web2Local = new LinkChanger();
        try {
            parsedResult = web2Local.linkChanger2local(dbObj);
//            System.err.println("web2local result: " + parsedResult);
            dbObj.setEstado(dbObj.DB_STATE_COMPLETE);
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        return attributes;
    }

    private void removeHeaderMetaTag(String path) {
        boolean flag = false;
        BufferedReader reader = null;

        try {
            reader = new BufferedReader(new FileReader(path));
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        }

        String line = null;
        StringBuilder stringBuilder = new StringBuilder();
        String ls = System.getProperty("line.separator");

        try {
            while ((line = reader.readLine()) != null) {
                if (line.toLowerCase().contains("<body") && flag == false) {
                    flag = true;
                }
                if (!(line.toLowerCase().contains("meta")) || !(line.toLowerCase().contains("option"))) {
                    stringBuilder.append(line);
                    stringBuilder.append(ls);
                }
            }
            boolean fileResult = false;
            fileResult = this.fileWriter(path, stringBuilder.toString());
        } catch (IOException e) {
        }
    }

    public boolean fileWriter(String file, String value) {
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(file));
            writer.write(value);

        } catch (IOException e) {
            return false;
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                return false;
            }
        }
        return true;
    }

    private ArrayList<Ficheiro> turn2File(ArrayList<String> attributeList, Ficheiro obj, String tipo) {
        ArrayList<Ficheiro> attributes = new ArrayList<Ficheiro>();
        Ficheiro fx;
        boolean exists = false;

        boolean result = false;
        String cursor[] = {".htm", "html", ".asp", ".php", ".jpg", ".gif", ".png", "zip"};
        String ficheiro;

        for (String value : attributeList) {
            for (int i = 0; i < cursor.length; i++) {
                if (value.contains(cursor[i])) {
                    result = true;
                }
            }
            if (result == true) {
                if (value.toLowerCase().contains(obj.getDominio().toLowerCase()) && !(value.toLowerCase().equals(obj.getDominio().toLowerCase()))) {
                    if (value.contains("?")) {
                        value = value.split("\\?")[0];
                    }
                    ficheiro = this.getFicheiro(value, obj);

                    fx = new Ficheiro(null, obj.getDominio(), ficheiro, obj.DB_STATE_DOWNLOAD, 0, value, null, null, 0, new Date());

                    exists = this.verifyExistance(fx, attributes);
                    if (exists == true) {
                        attributes.add(fx);
                    }
                } else {
                    if (!(value.toLowerCase().contains(obj.getDominio().toLowerCase())) && !(value.toLowerCase().contains("."))) {

                        ficheiro = value;
                        fx = new Ficheiro(null, obj.getDominio(), ficheiro, obj.DB_STATE_DOWNLOAD, 0, obj.getDominio() + value + "/", null, null,
                                0, new Date());

                        exists = this.verifyExistance(fx, attributes);
                        if (exists == true) {
                            attributes.add(fx);
                        }
                    }
                }
                result = false;
            } else {
                String dir = socof_webcrawler.SOCOF_WebCrawler.getPATH();
                File localDir = new File(dir);
                if (!localDir.exists()) {
                    boolean success = (new File(dir)).mkdirs();
                }
            }
        }

        this.fileWriter("c:\\teste\\heu.txt", attributes.toString());
        return attributes;
    }

    public boolean verifyExistance(Ficheiro fx, ArrayList<Ficheiro> attributes) {
        for (Ficheiro ficheiro : attributes) {
            if (fx.getCaminhosite().equalsIgnoreCase(ficheiro.getCaminhosite())) {
                return false;
            }
        }
        return true;
    }

    private String getFicheiro(String value, Ficheiro obj) {
        String temp = value.replace(obj.getDominio(), "");
        String[] subDirs = temp.split("/");
        return subDirs[subDirs.length - 1];
    }
}
